<template>
  <div class="px-2 flex flex-row gap-4 justify-between">
    <n-button @click="toggleSidebar" size="small" circle>
      <template #icon>
        <n-icon v-if="showSidebar">
          <ChevronLeft24Regular />
        </n-icon>
        <n-icon v-else>
          <ChevronRight24Regular />
        </n-icon>

      </template>
    </n-button>
    <div>
      <n-ellipsis style="max-width: 240px">{{ currentFileName }}</n-ellipsis>
    </div>
    <n-button  @click="()=>reType=!reType" size="small" circle>
      <template #icon>
        <n-icon>
          <SettingFilled />
        </n-icon>
      </template>
    </n-button>
    <n-button @click="toggleFullscreen" size="small" circle>
      <template #icon>
        <n-icon>
          <FullScreenMaximize24Regular />
        </n-icon>
      </template>
    </n-button>
  </div>
  <div class="content flex h-full flex-row gap-4 items-start p-4">
    <audio ref="audioPlayer" @ended="isPlaying = false"></audio>
    <!-- 固定左侧信息区域宽度并限制高度 -->
    <div v-show="showSidebar"
      class="info w-80 flex flex-col bg-white rounded-lg shadow-md p-4 max-h-screen overflow-hidden">


      <div class="upload mb-4">


        <n-upload ref="uploadRef" :max="1" @change="handleChange" accept="application/pdf" :show-file-list="false">
          <n-button>打开文件</n-button>
        </n-upload>
      </div>

      <div class="toolbar flex flex-col gap-3 mb-4">
        <div class="flex flex-row gap-2 items-center">

          <n-pagination v-model:page="page" :page-count="pageCount" size="small" simple :on-update:page="onInputPage" />
          <n-button strong secondary type="primary" @click="" size="small">
            跳转
          </n-button>
        </div>

        <div class="flex flex-row gap-2">
          <n-button @click="parseWord" type="primary" secondary size="small" class="flex-1">
            <template #icon>
              <n-icon>
                <TextBulletListSquare24Regular />
              </n-icon>
            </template>
            解析页面
          </n-button>
        </div>

        <div class="flex flex-row gap-2 items-center">
          <n-icon size="18" color="#666">
            <Search24Regular />
          </n-icon>
          <span class="text-sm text-gray-600">缩放:</span>
          <n-slider @dragend="onScaleChange" v-model:value="scale" :step="0.1" :min="0.5" :max="10" class="flex-1" />
          <span class="text-sm text-gray-600 w-10">{{ scale.toFixed(1) }}x</span>
        </div>
      </div>

      <div class="word-section flex-1 flex flex-col min-h-0">
        <div class="section-title flex flex-row items-center gap-2 mb-2">
          <n-icon size="18" color="#1890ff">
            <Book24Regular />
          </n-icon>
          <span class="font-medium text-gray-700">生词列表</span>
        </div>

        <ul class="wordList flex-1 overflow-auto max-h-100 max-w-100 bg-gray-50 rounded-lg p-2">
          <li v-for="item in sortedWords" :key="item.word"
            class="bg-white rounded-lg shadow-sm mb-2 hover:shadow transition-shadow">
            <div class="p-3">
              <div class="flex flex-row gap-2 justify-between items-center">
                <div class="font-medium text-gray-800">{{ item.word }}</div>
                <div class="flex flex-row gap-1 items-center">
                  <n-icon size="20" @click="playAudio(item.word)"
                    :color="currentPlayingWord === item.word && isPlaying ? '#18a058' : '#666'"
                    class="cursor-pointer hover:text-blue-500 transition-colors">
                    <PlayCircle24Regular />
                  </n-icon>
                  <span class="text-sm text-gray-500">{{ item.freq }}</span>
                </div>
              </div>
              <div class="flex flex-row gap-2 justify-end mt-2">
                <n-rate :default-value="item.star" :count="3"
                  :on-update:value="(star: number) => addWord(item.word, star)" size="small" />
              </div>
              <div v-if="store.myDict" class="translate text-xs text-gray-600 mt-1 italic">{{
                store.myDict.get(item.word)?.translation }}</div>
            </div>
          </li>
        </ul>
      </div>
    </div>



    <!-- PDF区域设置为可滚动且不超过浏览器高度 -->
    <div class="pdf flex-1 flex flex-col bg-white rounded-lg shadow-md p-4 max-h-screen overflow-auto">
      <div id="pageContainer" style="border: solid 1px #e5e5e5; flex-shrink: 0; margin: 0 auto; width: 100%;"
        class="rounded">
        <div v-if="reType" class="text-content whitespace-pre-line" :style="{ fontSize: scale*100+'%' }">
          {{ getRetypeText }}
        </div>
        <div v-else>
          <div v-if="!haveText" class="text-center py-10 text-gray-500">当前页面没有文字</div>
          <svg :width="viewport?.width + 'px'" :height="viewport?.height + 'px'" font-size="1">
            <text v-for="item in transformItems" :transform="item.transform" font-family="serif">{{ item.text.str
              }}</text>
          </svg>
        </div>
      </div>
      <canvas style="flex-shrink: 0; margin: 0 auto;" id="pdf-canvas" ref="canvas" class="rounded"></canvas>
    </div>
  </div>

  <!-- 悬浮的退出全屏按钮 -->
  <div v-if="isFullscreen" class="fullscreen-exit-btn">
    <n-button @click="exitFullscreen" size="large" circle type="primary">
      <template #icon>
        <n-icon>
          <PictureInPictureExit16Filled />
        </n-icon>
      </template>
    </n-button>
  </div>
</template>

<script setup lang="ts">
import { PlayCircle24Regular, TextBulletListSquare24Regular, Search24Regular, Book24Regular, ChevronLeft24Regular, ChevronRight24Regular, FullScreenMaximize24Regular, PictureInPictureExit16Filled } from '@vicons/fluent'
import * as pdfjsLib from 'pdfjs-dist';
import { ref } from 'vue';
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.mjs?url'
import type { TextItem, TextMarkedContent } from 'pdfjs-dist/types/src/display/api';
import { computed } from 'vue';
import { useDictStore } from '../store/dict';
import type { UploadFileInfo } from 'naive-ui';
import { XxApiTranslator } from '../services/translate/XxApiTranslator';

import { useMessage } from 'naive-ui'
import { TranslatorFactory } from '../services/translate/TranslatorFactory';
const message = useMessage()

// 添加currentFileName变量
const currentFileName = ref<string>('')

const parsedPage = new Set()
interface WordItem {
  word: string;
  freq: number;
  translation: string;
  star: number;
}
const uploadRef = ref()
console.log(pdfjsLib.version, pdfjsWorker)
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker

let wordDao = WordDaoFactory.getWordDao()
let translator = new XxApiTranslator()

const translatorFactory = new TranslatorFactory()
let translatorKey = localStorage.getItem('translator')
if (translatorKey != null && translatorFactory.getAllTranslators().has(translatorKey)) {
  if (translatorFactory.getTranslator(translatorKey) != null) {
    translator = translatorFactory.getTranslator(translatorKey)!
    message.success('已切换翻译器为：' + translatorKey)
  }
}

const store = useDictStore()

store.fetchWords()

const canvas = ref<HTMLCanvasElement>();

const page = ref(1)
const pageCount = ref(1)

// 重排版
const reType = ref(true)

const getRetypeText = computed(() => {
  let result = ''
  for (let item of textItems.value) {
    result += item.str
    if(item.str.trim().endsWith(".")) {
      result += '\n'
    }
    result+=' '
  }
  return result
})

let pdfProxy: pdfjsLib.PDFDocumentProxy | null = null

const currentDict = ref<Map<String, WordItem>>(new Map())

const items = ref<Array<TextItem | TextMarkedContent>>([])
let viewport = ref<pdfjsLib.PageViewport | null>(null)

const textItems = computed(() => items.value.filter(item => 'str' in item))
const transformItems = computed(() => {
  return textItems.value.map(item => {
    return {
      text: item,
      transform: getTransform(item.transform)
    }
  })
})
const sortedWords = computed(() => {
  // 将 Map 转成数组，并解构出 value（WordItem）
  const wordsArray = Array.from(currentDict.value.values());

  // 按照 freq 降序排序
  return wordsArray.sort((a, b) => b.freq - a.freq);
});

const handleChange = (options: { file: UploadFileInfo }) => {
  if (options.file && options.file.name.endsWith('.pdf')) {
    console.log("is pdf:")
    if (options.file.file != null) {
      // 设置当前文件名
      currentFileName.value = options.file.name
      loadPdf(options.file.file)
    }
  }
}

function onInputPage(pageNum: number) {
  page.value = pageNum
  loadPage(page.value)
}

const haveText = computed(() => {
  return transformItems.value.length > 0
})

async function loadPage(pageNum: number) {
  console.log("load page start");

  if (pdfProxy == null) {
    return
  }
  console.log("pdf proxy:", pdfProxy, pageNum)
  const page = await pdfProxy.getPage(pageNum)
  viewport.value = page.getViewport({ scale: scale.value });

  let textContent = await page.getTextContent();
  console.log("textContent:", textContent)
  items.value = textContent.items

  // if (canvas.value != null) {
  //   // Prepare canvas using PDF page dimensions
  //   var context = canvas.value.getContext('2d');
  //   canvas.value.height = viewport.value.height;
  //   canvas.value.width = viewport.value.width;

  //   if (context == null) {
  //     return;
  //   }
  //   // Render PDF page into canvas context
  //   var renderContext = {
  //     canvasContext: context,
  //     viewport: viewport.value
  //   };


  //   // const svg = buildSVG(viewport, textContent);
  //   // document.getElementById("pageContainer").append(svg);
  //   // console.log("svg", svg)
  //   if (renderContext != null) {
  //     var renderTask = page.render(renderContext);
  //     renderTask.promise.then(function () {
  //       console.log('Page rendered');
  //     });
  //   }


  // }
}
async function loadPdf(file: File) {
  console.log("load pdf:", file)

  const fileReader = new FileReader();
  fileReader.onload = async function () {
    const typedArray = new Uint8Array(this.result as ArrayBuffer);
    const pdf = await pdfjsLib.getDocument({
      data: typedArray,
      cMapUrl: "/cmaps/"
    }).promise
    pdfProxy = pdf
    uploadRef.value.clear()
    pageCount.value = pdf.numPages

    parsedPage.clear()
    currentDict.value.clear()
    loadPage(1)
    // var viewport = page.getViewport({ scale: scale });

    // if (canvas.value != null) {
    //   // Prepare canvas using PDF page dimensions
    //   var context = canvas.value.getContext('2d');
    //   canvas.value.height = viewport.height;
    //   canvas.value.width = viewport.width;

    //   // Render PDF page into canvas context
    //   var renderContext = {
    //     canvasContext: context,
    //     viewport: viewport
    //   };
    //   console.log(await page.getTextContent())
    //   console.log(await page.getAnnotations())
    //   console.log(await page.getStructTree())
    // const svg = buildSVG(viewport.value, textContent);
    //  document.getElementById("pageContainer").append(svg);
    // console.log("svg", svg)
    //   var renderTask = page.render(renderContext);
    //   renderTask.promise.then(function () {
    //     console.log('Page rendered');
    //     const textLayerDiv = document.getElementById('text-layer');


    //   });

    // }


  }
  fileReader.readAsArrayBuffer(file)
}

function getTransform(transform: Array<any>): string {

  if (viewport.value == null) {
    console.log("view port is null")
    return ''
  }
  const tx = pdfjsLib.Util.transform(
    pdfjsLib.Util.transform(viewport.value.transform, transform),
    [1, 0, 0, -1, 0, 0]
  );
  let result = "matrix(" + tx.join(" ") + ")"
  // console.log("get view:", result)

  return result
}
const scale = ref(1)

let scaleStr = localStorage.getItem("scale")
if (scaleStr != null) {
  scale.value = parseFloat(scaleStr)
  console.log("scale:", scale.value)
}

function onScaleChange() {
  console.log("scale to", scale.value)
  localStorage.setItem("scale", scale.value.toString())
  loadPage(page.value)
}

function isPureAlphabet(word: string): boolean {
  // 使用正则表达式匹配仅包含大小写字母的字符串
  return /^[A-Za-z]+$/.test(word);
}

async function addWord(word: string, star: number) {
  console.log("on add word:", word, star)
  let translation = "";
  let definition = "";
  if (star == 3) {
    // store.myDict.delete(word)
    currentDict.value.delete(word)
  } else if (star == 1) {
    let res = await translator.translate(word, 'en')
    // let res = await apiClient.get<WordResponse>('/definition', { params: { word: word } })
    if (res == null) {
      message.error("翻译失败,词库里没有")
      return;
    }
    console.log("query res:", res)
    translation = res.translation
    definition = res.definition || ''
    store.addMyWord(word, star, translation, definition)
  }
  wordDao.addOrUpdateWord({ word, star, translation, definition })

  // apiClient.post<WordRecord>('/words', { word, star, translation, defintion }).then(res => {
  //   console.log("addWord res", res);
  // });
}

// 提取生词 自动显示
function parseWord() {
  const isNewPage = parsedPage.has(page.value)
  if (!isNewPage) {
    parsedPage.add(page.value)
  } else {
    return
  }
  for (let item of textItems.value) {
    let text = item.str
    let wordList = text.split(/[^a-zA-Z]+/)
    console.log(wordList)
    for (let word of wordList) {
      if (word == "") {
        continue
      }
      // 过滤非纯字母的词,只保留字母
      if (!isPureAlphabet(word)) {
        console.log("跳过非纯字母词:", word);
        continue;
      }
      word = word.toLowerCase()
      if (word.length == 1) {
        continue
      }
      // 如果已经是认识的，就跳过
      if (store.isKnownWord(word)) {
        continue
      }

      if (currentDict.value.has(word)) {
        let now = currentDict.value.get(word)
        if (now?.freq) {
          now.freq = now.freq + 1
        }
        if (now != null) {
          currentDict.value.set(word, now)
        }
      } else {
        let data = { freq: 1, word: word, translation: '', star: 0 }
        if (store.myDict.has(word)) {
          let saveWord = store.myDict.get(word)
          data['translation'] = saveWord?.translation || ''
          data['star'] = saveWord?.star || 0

        }
        currentDict.value.set(word, data)
      }

    }
    // console.log("words:", currentDict.value)
  }


}


const audioPlayer = ref<HTMLAudioElement | null>(null)
const currentPlayingWord = ref<string | null>(null)
const isPlaying = ref(false)

async function playAudio(word: string) {
  console.log("playing audio for word:", word)
  try {
    // 如果正在播放同一个单词，则暂停
    if (currentPlayingWord.value === word && isPlaying.value) {
      pauseAudio()
      return
    }

    // 停止当前播放
    if (audioPlayer.value) {
      audioPlayer.value.pause()
    }

    // 设置新的音频源（这里使用Google翻译API示例）
    const audioUrl = `https://dict.youdao.com/dictvoice?audio=${encodeURIComponent(word)}&type=2`

    if (audioPlayer.value) {
      currentPlayingWord.value = word
      audioPlayer.value.src = audioUrl
      await audioPlayer.value.play()
      isPlaying.value = true
    }
  } catch (error) {
    console.error('播放音频失败:', error)
    message.error('音频播放失败: ' + (error as Error).message)
  }
}

function pauseAudio() {
  if (audioPlayer.value) {
    audioPlayer.value.pause()
    isPlaying.value = false
    currentPlayingWord.value = null
  }
}

import { onUnmounted } from 'vue'
import { SettingFilled } from '@vicons/antd';
import { WordDaoFactory } from '../services/dao/WordDaoFactory';

// 添加控制侧边栏显示的状态
const showSidebar = ref(true)

// 添加全屏模式状态
const isFullscreen = ref(false)

// 添加切换侧边栏显示的方法
function toggleSidebar() {
  showSidebar.value = !showSidebar.value
}

// 全屏模式相关方法
function toggleFullscreen() {
  isFullscreen.value = true
  // 通过全局事件通知Main.vue隐藏菜单
  window.dispatchEvent(new CustomEvent('toggleFullscreen', { detail: { isFullscreen: true } }))
}

function exitFullscreen() {
  isFullscreen.value = false
  // 通过全局事件通知Main.vue显示菜单
  window.dispatchEvent(new CustomEvent('toggleFullscreen', { detail: { isFullscreen: false } }))
}

// 监听来自父组件的全屏状态变化
window.addEventListener('fullscreenChange', (event: any) => {
  isFullscreen.value = event.detail.isFullscreen
})

onUnmounted(() => {
  if (audioPlayer.value) {
    audioPlayer.value.pause()
  }
})
</script>

<style scoped>
.content {
  background-color: #f5f5f5;
  height: 100%;
  overflow: hidden;
}

.info {
  height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.test {
  height: 600px;
  border: 2px red solid;
  flex-shrink: 0;
}

.translate {
  font-style: italic;
}

.pdf {
  overflow: auto;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.wordList {
  overflow: auto;
  flex-shrink: 1;
  min-height: 0;
}

.wordList::-webkit-scrollbar {
  width: 6px;
}

.wordList::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 10px;
}

.wordList::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 10px;
}

.wordList::-webkit-scrollbar-thumb:hover {
  background: #a1a1a1;
}


.text-content {
  font-family: 'NotoSans';
}

.fullscreen-exit-btn {
  position: fixed;
  bottom: 20px;
  right: 20px;
  z-index: 9999;
}
</style>